package in.rob.client.page;
import in.lib.Constants;
import in.lib.URLMatcher;
import in.lib.adapter.ProfilePostAdapter;
import in.lib.annotation.InjectView;
import in.lib.annotation.OnClick;
import in.lib.event.DeletePostEvent;
import in.lib.event.NewPostEvent;
import in.lib.event.ProfileUpdatedEvent;
import in.lib.handler.UserFollowResponseHandler;
import in.lib.handler.UserUnFollowResponseHandler;
import in.lib.handler.streams.ProfilePostsResponseHandler;
import in.lib.handler.streams.UserDetailsResponseHandler;
import in.lib.helper.ResponseHelper;
import in.lib.helper.ThemeHelper;
import in.lib.manager.APIManager;
import in.lib.manager.SettingsManager;
import in.lib.utils.CodeUtils;
import in.lib.utils.Views;
import in.lib.view.AvatarView;
import in.lib.view.LinkTouchMovementMethod;
import in.lib.view.LinkifiedTextView;
import in.model.Post;
import in.model.SimpleUser;
import in.model.User;
import in.rob.client.MainApplication;
import in.rob.client.ProfileActivity;
import in.rob.client.R;
import in.rob.client.SettingsActivity;
import in.rob.client.dialog.AvatarViewDialog;
import in.rob.client.page.base.PostStreamFragment;
import java.util.ArrayList;
import java.util.List;
import lombok.Getter;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.text.Html;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.squareup.otto.Subscribe;
/**
* Page used to display a user profile page Extends PostStreamFragment for basic
* stuff like onSaveInstanceState but implements its own initData(Bundle arguments)
*/
public class ProfilePage extends PostStreamFragment implements OnClickListener, OnLongClickListener
{
// arguments
@Getter private User user;
private boolean userLoaded = false;
// views
@OnClick @Getter @InjectView(R.id.follow_button) public Button mFollowBtn;
@OnClick @InjectView(R.id.edit_button) public Button mEditBtn;
@OnClick @InjectView(R.id.avatar) public AvatarView mAvatar;
@InjectView(R.id.verification) public TextView mVerification;
@InjectView(R.id.follow_count) public TextView mFollowCountTv;
@InjectView(R.id.follows_you) public TextView mFollowsYouTv;
@InjectView(R.id.username) public TextView mUsernameTv;
@InjectView(R.id.bio_text) public LinkifiedTextView mBioTextTv;
@InjectView(R.id.details_container) public View mDetailsContainer;
@Override public void retrieveArguments(Bundle arguments)
{
// get arguments
if (arguments != null && getUser() == null)
{
if (arguments.containsKey(Constants.EXTRA_USER))
{
setUser((User)arguments.getParcelable(Constants.EXTRA_USER));
userLoaded = true;
}
else if (arguments.containsKey(Constants.EXTRA_USER_ID))
{
setUser(new User());
getUser().setId(arguments.getString(Constants.EXTRA_USER_ID));
}
else if (arguments.containsKey(Constants.EXTRA_USER_NAME))
{
setUser(new User());
getUser().setId(arguments.getString(Constants.EXTRA_USER_NAME));
}
else
{
getActivity().finish();
}
}
}
public void setUser(User user)
{
this.user = user;
if (!user.getId().equals("-1"))
{
userLoaded = true;
}
}
@Override public void setupAdapters()
{
if (getAdapter() == null)
{
setAdapter(new ProfilePostAdapter(getContext(), R.layout.post_list_item, new ArrayList<Post>(), getUser().getId()));
}
else
{
setAdapter(getAdapter());
}
}
@Override public void onViewCreated(View view, Bundle arguments)
{
super.onViewCreated(view, arguments);
getHeadedListView().setHeaderView(R.layout.profile_header_stub);
Views.inject(this, getHeadedListView());
mBioTextTv.setLinkMovementMethod(new LinkTouchMovementMethod());
mAvatar.setOnLongClickListener(this);
if (!userLoaded)
{
refreshUserDetails();
}
else
{
loadUserDetails();
}
}
@Override public void onResume()
{
super.onResume();
if (userLoaded)
{
if (SettingsManager.getCacheTimeout() > 0 && getCacheManager().fileOlderThan(String.format(Constants.CACHE_USER, getUser().getId()), System.currentTimeMillis() - SettingsManager.getCacheTimeout()))
{
refreshUserDetails();
}
}
}
public void extractUser()
{
List<SimpleUser> users = getCacheManager().readFileAsObject(Constants.CACHE_USERNAMES, new ArrayList<SimpleUser>());
List<String> usersStr = getCacheManager().readFileAsObject(Constants.CACHE_USERNAMES_STR, new ArrayList<String>());
if (getUser() != null && !usersStr.contains(getUser().getId()))
{
users.add(SimpleUser.parseFromUser(getUser()));
usersStr.add(getUser().getId());
}
getCacheManager().asyncWriteFile(Constants.CACHE_USERNAMES, users);
getCacheManager().asyncWriteFile(Constants.CACHE_USERNAMES_STR, usersStr);
users.clear();
usersStr.clear();
}
/**
* Loads the users details from the id. If it exists in cache, we'll use
* that if not, we'll use getUser() (if its not null)
*/
public void getUserDetails()
{
User user = User.loadUser(getUser().getId());
if (user != null)
{
setUser(user);
extractUser();
userLoaded = true;
loadUserDetails();
}
else
{
refreshUserDetails();
}
}
@Override public void onDestroy()
{
super.onDestroy();
getUser().save();
}
@Override public void onRefresh()
{
super.onRefresh();
if (((MainApplication)getApplicationContext()).isConnected())
{
refreshUserDetails();
}
}
/**
* Fetch user details from an API call
* @param userId
*/
public void refreshUserDetails()
{
UserDetailsResponseHandler handler = new UserDetailsResponseHandler(getApplicationContext());
ResponseHelper.getInstance().addResponse(String.format(Constants.RESPONSE_PROFILE_USER, user.getId()), handler, this);
APIManager.getInstance().getUserDetails(getUser().getId(), handler);
}
/**
* Loads user related UI. Should only be called when getUser() != null
*/
public void loadUserDetails()
{
boolean landscape = false;
try
{
landscape = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
}
catch (Exception e) {}
if (!getUser().isYou())
{
mEditBtn.setVisibility(View.GONE);
mFollowBtn.setVisibility(View.VISIBLE);
if (mFollowBtn.getTag(R.id.TAG_IS_LOADING) == null || !(Boolean)mFollowBtn.getTag(R.id.TAG_IS_LOADING))
{
if (getUser().getYouFollow())
{
TypedValue typedValue = new TypedValue();
getActivity().getTheme().resolveAttribute(R.attr.rbn_grey_button, typedValue, true);
mFollowBtn.setBackgroundResource(typedValue.resourceId);
}
mFollowBtn.setText(getUser().getYouFollow() ? getString(R.string.unfollow) : getString(R.string.follow));
mFollowsYouTv.setText(getUser().isFollowingYou() ? getString(R.string.follows_you) : getString(R.string.doesnt_follow_you));
}
}
else
{
mFollowBtn.setVisibility(View.GONE);
mEditBtn.setVisibility(View.VISIBLE);
}
if (mAvatar.getTag(R.id.TAG_IMAGE_URL) == null || !((String)mAvatar.getTag(R.id.TAG_IMAGE_URL)).equals(getUser().getAvatarUrl()))
{
if (getUser().isAvatarDefault())
{
mAvatar.setImageResource(R.drawable.default_avatar);
}
else
{
ImageLoader.getInstance().displayImage(getUser().getAvatarUrl() + "?avatar=1&id=" + getUser().getId(), mAvatar, MainApplication.getAvatarImageOptions());
}
mAvatar.setTag(R.id.TAG_IMAGE_URL, getUser().getAvatarUrl());
}
String desc = getUser().getFormattedDescription();
mBioTextTv.setText(desc);
String[] name = CodeUtils.nameOrderParse(SettingsManager.getNameDisplayOrder(), getUser());
mUsernameTv.setText(name[0] + (TextUtils.isEmpty(name[1]) ? "" : "\n" + name[1]));
mFollowCountTv.setText(Html.fromHtml(String.format(getString(R.string.profile_stats), "<b>" + getUser().getFollowingCount() + "</b>", (landscape ? " - " : "<br />") + "<b>" + getUser().getFollowersCount() + "</b>", "<br /><b>" + getUser().getStarredCount() + "</b>", "<br /><b>" + getUser().getPostCount() + "</b>")));
if (!getUser().isCoverDefault())
{
setHeaderUrl(getUser().getCoverUrl());
}
if (!TextUtils.isEmpty(getUser().getVerifiedDomain()))
{
mVerification.setVisibility(View.VISIBLE);
mVerification.setText(getString(R.string.verified, getUser().getVerifiedDomain()));
}
if (getActivity() instanceof ProfileActivity)
{
if (((ProfileActivity)getActivity()).getCurrentFragment() == this)
{
((ProfileActivity)getActivity()).setTitle("@" + getUser().getMentionName());
}
((ProfileActivity)getActivity()).setUser(getUser());
getArguments().putString(Constants.EXTRA_TITLE, getString(R.string.at) + getUser().getMentionName());
getActivity().supportInvalidateOptionsMenu();
}
}
@Override public void fetchStream(String lastId, final boolean append)
{
ProfilePostsResponseHandler handler = new ProfilePostsResponseHandler(getApplicationContext(), append);
handler.setFailMessage(getString(R.string.user_stream_fail, "@" + user.getMentionName()));
ResponseHelper.getInstance().addResponse(String.format(Constants.RESPONSE_PROFILE_POSTS, user.getId()), handler, this);
APIManager.getInstance().getUserPosts(getContext(), getUser().getId(), lastId, handler);
}
@Override public void onClick(View v)
{
if (v == mFollowBtn)
{
if (v.getTag(R.id.TAG_IS_LOADING) != null && (Boolean)v.getTag(R.id.TAG_IS_LOADING)) return;
boolean landscape = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
final int redButton = ThemeHelper.getDrawableResource(getContext(), R.attr.rbn_red_button);
final int greyButton = ThemeHelper.getDrawableResource(getContext(), R.attr.rbn_grey_button);
if (getUser().getYouFollow())
{
getUser().setYouFollow(false);
getUser().setFollowersCount(getUser().getFollowersCount() - 1);
mFollowBtn.setEnabled(false);
mFollowBtn.setTag(R.id.TAG_IS_LOADING, true);
mFollowBtn.setBackgroundResource(redButton);
mFollowBtn.setText(getString(R.string.follow));
mFollowCountTv.setText(Html.fromHtml(String.format(getString(R.string.profile_stats), "<b>" + getUser().getFollowingCount() + "</b>", (landscape ? " - " : "<br />") + "<b>" + getUser().getFollowersCount() + "</b>", "<br /><b>" + getUser().getStarredCount() + "</b>", "<br /><b>" + getUser().getPostCount() + "</b>")));
APIManager.getInstance().unfollowUser(getUser().getId(), new UserUnFollowResponseHandler()
{
@Override public void onFinish(boolean failed)
{
super.onFinish(failed);
mFollowBtn.setTag(R.id.TAG_IS_LOADING, false);
mFollowBtn.setEnabled(true);
if (ProfilePage.this.getUser() != null)
{
if (failed)
{
ProfilePage.this.getUser().setFollowersCount(ProfilePage.this.getUser().getFollowersCount() + 1);
ProfilePage.this.getUser().setYouFollow(true);
mFollowBtn.setText(R.string.unfollow);
mFollowBtn.setBackgroundResource(greyButton);
Toast.makeText(getContext(), getString(R.string.unfollow_failed_formatted, ProfilePage.this.getUser().getMentionName()), Toast.LENGTH_SHORT).show();
}
else
{
ProfilePage.this.getUser().setYouFollow(false);
}
}
}
});
}
else
{
getUser().setYouFollow(true);
getUser().setFollowersCount(getUser().getFollowersCount() + 1);
mFollowBtn.setEnabled(false);
mFollowBtn.setTag(R.id.TAG_IS_LOADING, true);
mFollowBtn.setBackgroundResource(greyButton);
mFollowBtn.setText(getString(R.string.unfollow));
mFollowCountTv.setText(Html.fromHtml(String.format(getString(R.string.profile_stats), "<b>" + getUser().getFollowingCount() + "</b>", (landscape ? " - " : "<br />") + "<b>" + getUser().getFollowersCount() + "</b>", "<br /><b>" + getUser().getStarredCount() + "</b>", "<br /><b>" + getUser().getPostCount() + "</b>")));
APIManager.getInstance().followUser(getUser().getId(), new UserFollowResponseHandler()
{
@Override public void onFinish(boolean failed)
{
super.onFinish(failed);
mFollowBtn.setTag(R.id.TAG_IS_LOADING, false);
mFollowBtn.setEnabled(true);
if (ProfilePage.this.getUser() != null)
{
if (failed)
{
Context c = ProfilePage.this.getContext();
ProfilePage.this.getUser().setFollowersCount(ProfilePage.this.getUser().getFollowersCount() - 1);
ProfilePage.this.getUser().setYouFollow(false);
mFollowBtn.setText(R.string.follow);
mFollowBtn.setBackgroundResource(redButton);
if (c != null)
{
String message = c.getString(R.string.follow_failed) + " @" + ProfilePage.this.getUser().getMentionName();
if (getConnectionInfo().responseCode == 507)
{
message = c.getString(R.string.too_many_follow);
}
Toast.makeText(c, message, Toast.LENGTH_LONG).show();
}
}
else
{
ProfilePage.this.getUser().setYouFollow(true);
}
}
}
});
}
}
else if (v == mAvatar)
{
Bundle args = new Bundle();
args.putString(Constants.EXTRA_IMAGE, getUser().getAvatarUrl());
FragmentManager fragmentManager = getFragmentManager();
AvatarViewDialog lightboxFragment = new AvatarViewDialog();
lightboxFragment.setArguments(args);
lightboxFragment.show(fragmentManager, "dialog");
}
else if (v == mEditBtn)
{
Intent settings = new Intent(getContext(), SettingsActivity.class);
settings.putExtra(Constants.EXTRA_START_PAGE, 0);
startActivity(settings);
}
else if (v == mVerification)
{
String url = getUser().getVerifiedDomain();
if (!getUser().getVerifiedDomain().startsWith("http"))
{
url = "http://" + url;
}
Intent view = new Intent(getContext(), URLMatcher.class);
view.setData(Uri.parse(url));
startActivity(view);
}
}
@Subscribe public void onProfileUpdated(ProfileUpdatedEvent event)
{
if (event.getUser().getId().equals(user.getId()))
{
setHeaderUrl(event.getUser().getCoverUrl());
ImageLoader.getInstance().displayImage(event.getUser().getAvatarUrl() + "?avatar=1&id=" + event.getUser().getId(), mAvatar, MainApplication.getAvatarImageOptions());
mAvatar.setTag(R.id.TAG_IMAGE_URL, getUser().getAvatarUrl());
}
}
@Subscribe @Override public void onPostRecieved(NewPostEvent event)
{
Post p = event.getPost();
if (p != null)
{
if (p.getPoster().getId() == getUser().getId())
{
super.onPostRecieved(event);
}
}
}
@Subscribe @Override public void onPostDeleted(DeletePostEvent event)
{
super.onPostDeleted(event);
}
@Override public boolean onLongClick(View v)
{
if (v.getId() == R.id.avatar)
{
mAvatar.triggerLongPress(getUser());
return true;
}
return false;
}
@Override public String getCacheFileName()
{
return String.format(Constants.CACHE_USER_TIMELINE_LIST_NAME, getUser().getId());
}
@Override public String[] getResponseKeys()
{
return new String[]
{
String.format(Constants.RESPONSE_PROFILE_POSTS, user.getId()),
String.format(Constants.RESPONSE_PROFILE_USER, this.user.getId())
};
}
}